/**
 * 所有版权归 广西梧州 陈锦韬 所有
 *
 * @Title: AbstractSqlHandler
 * @Package com.rx.core.dbase
 * @Description: 多表查询
 * @author: 陈锦韬
 * @date: 2021\7\22 0022
 * @version V1.0
 * @Copyright: 2021 陈锦韬  All rights reserved.
 */
package com.rx.core.dbase;

import com.rx.core.dbase.mutil.param.MutilTableParameter;
import com.rx.core.iface.RelationQuery;
import com.rx.core.iface.ReturnInputMode;
import com.rx.core.util.EmptyChecker;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author: Administrator
 * @Description: 多表查询
 * @date: 2021\7\22 0022
 */
@Slf4j
public abstract class AbstractSqlHandler {

    protected void setFieldValue(Object object,Map<String,Field> fieldMap,String column,Object value) throws IllegalAccessException {
        if (EmptyChecker.isEmpty(object)){
            return;
        }
        Field field = fieldMap.get(column);
        if (EmptyChecker.isEmpty(field)){
            return;
        }
        field.setAccessible(true);
        field.set(object,value);
    }

    protected List convertFromResultSet(ResultSet resultSet, MutilTableParameter mutilTableParam) throws SQLException, IllegalAccessException, InstantiationException {
        //获取键名
        ResultSetMetaData md = resultSet.getMetaData();
        //获取列的数量
        int columnCount = md.getColumnCount();
        List list = new ArrayList<>();
        while (resultSet.next()){
            Object mainObject = mutilTableParam.getMainClass().newInstance();
            Object secondObject = mutilTableParam.getSecondClass().newInstance();
            Object threeObject = null;
            if (mainObject instanceof RelationQuery){
                ((RelationQuery) mainObject).assignRelation(secondObject);
            }
            if (null != mutilTableParam.getThreeClass()){
                threeObject = mutilTableParam.getThreeClass().newInstance();
                if (secondObject instanceof RelationQuery){
                    ((RelationQuery) secondObject).assignRelation(threeObject);
                }
            }
            list.add(mainObject);
            for (int i =1; i <= columnCount; i++) {
                //获取键名及值
                if (mutilTableParam.getMainTable().equalsIgnoreCase(md.getTableName(i))){
                    setFieldValue(mainObject,mutilTableParam.getMainFieldMap(),md.getColumnName(i),resultSet.getObject(i));
                }else if (mutilTableParam.getSecondTable().equalsIgnoreCase(md.getTableName(i))){
                    setFieldValue(secondObject,mutilTableParam.getSecondFieldMap(),md.getColumnName(i),resultSet.getObject(i));
                }else if (md.getTableName(i).equalsIgnoreCase(mutilTableParam.getThreeTable())){
                    setFieldValue(threeObject,mutilTableParam.getThreeFieldMap(),md.getColumnName(i),resultSet.getObject(i));
                }
            }
        }
        return list;
    }
    protected void closePrepare(PreparedStatement preparedStatement){
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException sqlEx) {
                log.error(sqlEx.getMessage());
            }
        }
    }
    protected void closeConnect(Connection connection ){
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException sqlEx) {
                log.error(sqlEx.getMessage());
            }
            connection = null;
        }
    }
    public Object intercept(Invocation invocation,MutilTableParameter mutilTableParameter,ReturnInputMode getSql){
        Object[] queryArgs = invocation.getArgs();
        MappedStatement ms = (MappedStatement)queryArgs[0];
        Object parameter = queryArgs[1];
        // 双表内联参数
        String sql = (String)getSql.handle(parameter);
        // 老sql
        BoundSql boundSql = ms.getBoundSql(parameter);
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try{
            connection = ms.getConfiguration().getEnvironment().getDataSource().getConnection();
            log.info("sql:" + sql);
            preparedStatement = connection.prepareStatement(sql);
            // 设置参数
            ParameterHandler parameterHandler = new DefaultParameterHandler(ms,parameter,boundSql);
            parameterHandler.setParameters(preparedStatement);
            // 获取结果集
            resultSet = preparedStatement.executeQuery();
            // 赋值到model
            return convertFromResultSet(resultSet,mutilTableParameter);
        }catch (Exception e){
            log.error(e.getMessage());
        }finally {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException sqlEx) {
                    log.error(sqlEx.getMessage());
                }
                resultSet = null;
            }
            closePrepare(preparedStatement);
            preparedStatement = null;

            closeConnect(connection);
            connection = null;
        }
        return Collections.emptyList();
    }
}
